import sys
from PyQt6.QtGui import *
from PyQt6.QtWidgets import *
from PyQt6.QtCore import *
from PyQt6.QtCharts import *
from agh_obj import VehicleState, Vehicle, VehicleType, VEHICLE_NAMES
from color_palette import *
import toolbox

RIGHT_TABLE_WIDTH = 320

NO_NEED_PROGRESS_BAR_COLS = (0, 1, 2)

GATE_TABLE_COL_COUNT = 10
GATE_TABLE_HEADER_LABELS = ["停机位", "航班号", "到达时间"] + list(VEHICLE_NAMES)

VEHICLE_TABLE_COL_COUNT = 3
VEHICLE_TABLE_HEADER_LABELS = ["车型", "总辆数", "派出辆数"]

FLIGHT_TABLE_COL_COUNT = 3
FLIGHT_TABLE_HEADER_LABELS= ["航班号", "停机位", "进港时间"]

OP_TABLE_COL_COUNT = 3
OP_TABLE_HEADER_LABELS= ["车型和编号", "出发时间", "路线"]

class GateTableItemDelegate(QStyledItemDelegate):
    def __init__(self, parent = None):
        super().__init__(parent)

    def paint(self, painter:QPainter, option, index):
        if index.column() not in NO_NEED_PROGRESS_BAR_COLS:

            if option.state & QStyle.StateFlag.State_Selected:
                painter.fillRect(option.rect, option.palette.highlight())

            rect = option.rect.adjusted(4, 4, -4, -4)
            if isinstance(index.data(), str):
                if index.data() == "暂无分配":
                    self.draw_state(painter, rect, NO_VEHICLE_COLOR, "暂无分配")
                else:
                    self.draw_state(painter, rect, DONT_NEED_VEHICLE_COLOR, "无需服务")
                return

            vehicle_state = index.data()[0]
            progress_value = index.data()[1]

            if vehicle_state == VehicleState.Coming:
                self.draw_state_with_progress_value(painter, rect, VEHICLE_COMING_COLOR, "行驶中", progress_value)
            elif vehicle_state == VehicleState.Waiting:
                self.draw_state(painter, rect, VEHICLE_WAITING_COLOR, "等待中")
            elif vehicle_state == VehicleState.Serving:
                self.draw_state_with_progress_value(painter, rect, VEHICLE_COMPLETE_COLOR, "服务中", progress_value)
            elif vehicle_state == VehicleState.Complete:
                self.draw_state(painter, rect, VEHICLE_COMPLETE_COLOR, "完成")
            else:
                print("出错", index.data())
                pass
        else:  
            super().paint(painter, option, index)

    def sizeHint(self, option, index):
        return super().sizeHint(option, index)

    def draw_state(self, painter:QPainter, rect:QRect, color:QColor, str_value:str):
        painter.fillRect(rect, color)
        painter.setPen(Qt.GlobalColor.white)
        painter.drawText(rect, Qt.AlignmentFlag.AlignCenter, str_value)

    def draw_state_with_progress_value(self, painter:QPainter, rect:QRect, color:QColor, str_value:str, progress_value:int):
        completeRect = rect.adjusted(0, 0, int(rect.width() * (progress_value - 100) * 0.01), 0)
        painter.fillRect(completeRect, color)

        unCompleteRect = rect.adjusted(int(rect.width() * progress_value * 0.01), 0, 0, 0)
        painter.fillRect(unCompleteRect, VEHICLE_UNCOMPLETE_COLOR)

        painter.setPen(Qt.GlobalColor.white)
        painter.drawText(rect, Qt.AlignmentFlag.AlignCenter, str_value)

class ChartWidget(QWidget):
    def __init__(self) -> None:
        super().__init__()
        self.init_table_widget()
        self.init_chart_view()
        self.cost_data_id = -1

        content_layout = QVBoxLayout()
        content_layout.addWidget(self.gate_table)
        content_layout.addWidget(self.cost_chart)
        content_layout.setSpacing(5)
        content_layout.setContentsMargins(0, 0, 0, 0)
        content_layout.setStretchFactor(self.cost_chart, 1)
        content_layout.setStretchFactor(self.gate_table, 1)

        self.clock_widget = toolbox.ClockWidget()
        self.clock_widget.setFixedWidth(RIGHT_TABLE_WIDTH)

        layout = QGridLayout(self)
        layout.addLayout(content_layout, 0, 0, 3, 1)
        layout.addWidget(self.operation_table, 0, 1, 3, 1)
        layout.addWidget(self.vehicle_table, 0, 2)
        layout.addWidget(self.flight_table, 1, 2)
        layout.addWidget(self.clock_widget, 2, 2)
        layout.setContentsMargins(10, 10, 10, 10)
    
    def clear(self):
        self.gate_table.setRowCount(0)
        self.operation_table.setRowCount(0)
        for series in self.cost_chart.chart().series():
            series.clear()

    def init_chart_view(self):
        chart = QChart()
        chart.setTitle("每次调度的代价")
        chart.setBackgroundRoundness(0)
        chart.layout().setContentsMargins(0, 0, 0, 0)
        
        chart.addSeries(QLineSeries())
        avg_line_series = QLineSeries()
        chart.addSeries(avg_line_series)
        chart.createDefaultAxes()

        chart.legend().markers(avg_line_series)[0].setVisible(False)
        chart.legend().setMarkerShape(QLegend.MarkerShape.MarkerShapeCircle)

        chart_view = QChartView()
        chart_view.setChart(chart)
        chart_view.setRenderHint(QPainter.RenderHint.Antialiasing, True)
        chart_view.setViewportUpdateMode(QGraphicsView.ViewportUpdateMode.BoundingRectViewportUpdate)
        self.cost_chart = chart_view
        return chart_view

    def init_table_widget(self):
        vehicle_table = toolbox.get_styled_table_widget()
        vehicle_table.setFixedWidth(RIGHT_TABLE_WIDTH)
        vehicle_table.setColumnCount(VEHICLE_TABLE_COL_COUNT)
        vehicle_table.setHorizontalHeaderLabels(VEHICLE_TABLE_HEADER_LABELS)
        vehicle_table.cellEntered.connect(self.show_vehicle_property)
        vehicle_table.setMouseTracking(True)
        self.vehicle_table = vehicle_table

        gate_table = toolbox.get_styled_table_widget()
        gate_table.setColumnCount(GATE_TABLE_COL_COUNT)
        gate_table.setHorizontalHeaderLabels(GATE_TABLE_HEADER_LABELS)
        gate_table.setItemDelegate(GateTableItemDelegate())
        self.gate_table = gate_table

        flight_table = toolbox.get_styled_table_widget()
        flight_table.setFixedWidth(RIGHT_TABLE_WIDTH)
        flight_table.setColumnCount(FLIGHT_TABLE_COL_COUNT)
        flight_table.setHorizontalHeaderLabels(FLIGHT_TABLE_HEADER_LABELS)
        self.flight_table = flight_table

        operation_table = toolbox.get_styled_table_widget()
        operation_table.setFixedWidth(RIGHT_TABLE_WIDTH)
        operation_table.setColumnCount(OP_TABLE_COL_COUNT)
        operation_table.setHorizontalHeaderLabels(OP_TABLE_HEADER_LABELS)
        self.operation_table = operation_table

    def update_cost_chart_view(self, cost_data, cost_sum, cost_avg, cost_max):
        chart = self.cost_chart.chart()
        line_series:QLineSeries = chart.series()[0]
        avg_line_series:QLineSeries = chart.series()[1]

        if len(cost_data) == 0:
            line_series.setName(f"总代价:0.0 平均代价:0.0 最大代价: 0.0")
            line_series.clear()
            avg_line_series.clear()
            return

        if self.cost_data_id == id(cost_data) and len(cost_data) == line_series.count():
            return

        if self.cost_data_id != id(cost_data):
            self.cost_data_id = id(cost_data)
            line_series.clear()
            
        for i in range(line_series.count(), len(cost_data)):
            line_series.append(i, cost_data[i])
    
        x_max = len(cost_data) - 1 
        y_max = cost_max

        avg_line_series.clear()
        avg_line_series.append(0, cost_avg)
        avg_line_series.append(x_max, cost_avg)

        line_series.setName(f"总代价:{cost_sum:.1f} 平均代价:{cost_avg:.1f} 最大代价: {cost_max:.1f}")
        # createDefaultAxes()本应自适应，但并没有表现出来，所以需要先自己算一下
        chart.axes()[0].setRange(0, x_max)
        chart.axes()[1].setRange(0, y_max * 1.25)
    
    def update_table_with_data(self, table:QTableWidget, data):
        table.setRowCount(len(data))
        for row in range(table.rowCount()):
            for col in range(table.columnCount()):
                item = QTableWidgetItem()
                item.setData(Qt.ItemDataRole.DisplayRole, data[row][col])
                item.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
                table.setItem(row, col, item)
                
    def update_gate_table(self, table_data):
        self.update_table_with_data(self.gate_table, table_data)
    
    def update_vehicle_table(self, table_data):
        self.update_table_with_data(self.vehicle_table, table_data)
    
    def update_flight_table(self, table_data):
        self.update_table_with_data(self.flight_table, table_data)

    def update_operation_table(self, table_data):
        self.update_table_with_data(self.operation_table, table_data)
    
    def set_operation_table_top_row(self, row:int):
        if self.operation_table.rowCount() == 0:
            return
        slider = self.operation_table.verticalScrollBar()
        value = (slider.maximum() - slider.minimum()) * row / self.operation_table.rowCount() + slider.minimum()
        slider.setValue(int(value))

    def show_vehicle_property(self, row:int, col:int):
        vtype = list(VehicleType)[row]
        QToolTip.showText(QCursor.pos(), VEHICLE_NAMES[row] + '\n' + str(Vehicle.property_of_type[vtype]), msecShowTime=100000)
